package org.example.mallweb.mallservice.service.serviceimpl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.example.mallcommon.result.ReturnResult;
import org.example.mallcommon.vio.SearchPageVio;
import org.example.mallcommon.vo.SearchVo;
import org.example.mallweb.mallservice.service.ElasticSearchService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 韩先楚
 * es服务实现类
 */
@Service
@EnableAsync
public class ElasticSearchServiceImpl implements ElasticSearchService {

    @Resource
    private RestHighLevelClient client;

    @Value("${es.name}")
    private String esName;

    /**
     * 根据id删除
     *
     * @param id
     */
    @Override
    @Async
    public void deleteById(Long id) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(esName, id.toString());
        updateRequest.doc(
                "status", 2
        );
        client.update(updateRequest, RequestOptions.DEFAULT);
    }

    /**
     * 修改或新增es
     */
    @Override
    @Async
    public void saveOrUpdate(SearchVo searchVo) throws IOException {
        IndexRequest id = new IndexRequest(esName).id(searchVo.getId().toString());
        IndexRequest source = id.source(JSONUtil.toJsonStr(searchVo), XContentType.JSON);
        client.index(source, RequestOptions.DEFAULT);
    }

    @Override
    public ReturnResult<SearchPageVio> searchArticle(Integer page, Integer size, String keywords) throws IOException {
        //获取查询条件
        SearchRequest searchRequest = new SearchRequest(esName);
        // 2.组织请求参数
        // 2.1.准备bool查询
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        // 2.2.关键字搜索
        bool.must(QueryBuilders.multiMatchQuery(
                keywords, "title", "description"
        ));
        // 2.3.品牌过滤
        bool.filter(QueryBuilders.termQuery("status", "1"));
        // 2.4.分页
        searchRequest.source().from((page - 1) * size);
        searchRequest.source().size(size);
        //2.5 高亮
        searchRequest.source().highlighter(
                SearchSourceBuilder.highlight()
                        .field("title")
                        .field("description")
                        .preTags("<em>")
                        .postTags("</em>")

        );
        // 2.5.bool查询
        searchRequest.source().query(bool);
        // 3.发送请求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 4.解析响应
        return handleResponse(response);

    }

    //解析响应
    private ReturnResult<SearchPageVio> handleResponse(SearchResponse response) {
        SearchPageVio searchPageVio = new SearchPageVio();
        SearchHits searchHits = response.getHits();
        // 1.获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        searchPageVio.setTotal(total);
        // 2.遍历结果数组
        SearchHit[] hits = searchHits.getHits();
        if (hits == null || hits.length == 0)
            return ReturnResult.success(searchPageVio);
        // 3.遍历结果数组
        List<SearchVo> searchVoList = new ArrayList<>();
        for (SearchHit hit : hits) {
            // 3.得到_source，也就是原始json文档
            String source = hit.getSourceAsString();
            // 4.反序列化并打印
            SearchVo item = JSONUtil.toBean(source, SearchVo.class);
            //获取高亮结果
            HighlightField title = hit.getHighlightFields().get("title");
            if (title != null) {
                item.setTitle( title.getFragments()[0].toString());
            }
            HighlightField description = hit.getHighlightFields().get("description");
            if (description != null) {
               item.setDescription( description.getFragments()[0].toString());
            }
            searchVoList.add(item);
        }
        searchPageVio.setData(searchVoList);
        return ReturnResult.success(searchPageVio);
    }


}
